'use strict';
module.exports = core;

// require解析文件方式
// json 以JSON.parse进行解析
// js 解析module.export或者export
// 其余格式文件 以js引擎进行解析，解析不了会报错
const path = require("path");
const colors = require("colors")
const semver = require("semver")  //外部依赖一般写上面
const userhome = require('userhome');
const pathExists = require('path-exists').sync;
const pkg = require("../package.json")
const constant = require('./const')
const log = require("@gsh-cli/log");
const exec = require('@gsh-cli/exec')
let argv;

async function core() {
  try {
    await prepare()
    registerCommand()
  } catch(error) {
    log.error(error)
  }
  // TODO
}

function registerCommand() {
  const commander = require('commander');
  const program = new commander.Command();
  program
  .name(Object.keys(pkg.bin)[0])
  .usage("<commander> [option]")
  .version(pkg.version)
  .option('-d, --debug','是否开启调试模式',false)
  .option('-tp --targetPath <targetPath>', '设置缓存目录')

  // 添加init命令
  program
  .command('init [programName]')
  .description('创建项目')
  .option('-f, --force', '是否强制覆盖文件', false)
  .action(exec)

  
  // 开启debug模式
  program.on('option:debug', function() {
    if (program.debug) {
      process.env.LOG_LEVEL = 'verbose';
    }
    log.level = process.env.LOG_LEVEL;
  })

  // 设置缓存目录
  program.on('option:targetPath', function() {
    process.env.CLI_TARGET_PATH = program.targetPath
  })

  // 无效命令处理
  program.on('command:*', function(obj) {
    const commands = program.commands.map(item => item.name)
    console.log(colors.red(`${obj[0]}是无效命令`))
    if (commands.length > 0) {
      console.log(colors.red(`有效命令为：${commands}`))
    }
  })

  // 命令模块解析生效
  program.parse(process.argv)

  // 如果没有传功能命令，则自动输出help，就是要有commander，option也不算
  if (program.args && program.args.length < 1) {
    program.outputHelp();
    // 加空行
    console.log()
  }
}

async function prepare() {
  checkVersion();
  checkNodeVersion();
  checkRoot();
  checkUserHome();
  // checkInputArgs();
  checkEnv();
  await checkNpmVersion();

}

// *** 1.检查版本号 ***
function checkVersion() {
  console.log(pkg.version)
}

// *** 2.检查node版本 ***
function checkNodeVersion() {
  // 怎么去检查？获取当前的版本号，并设置最小版本号，与之匹配
  // 需要什么交互？若不符合就抛出异常，且异常不能太过冗余
  // -- 获取当前版本号 --
  let currentVersion = process.version;
  // -- 获取规定最小版本号 --
  let lastestNodeVersion = constant.LASTEST_NODE_VERSION;
  // -- 版本比较 --
  if (!semver.gte(currentVersion, lastestNodeVersion)) {
    throw Error(colors.red(`当前node版本为${currentVersion}，请使用${lastestNodeVersion}以上的版本号`));
  }
}

// *** 3.检查是否是管理员权限，并对其进行降级 ***
function checkRoot() {
  // 获取系统权限 process.geteuid() 0代表管理员 如果不对其进行降级，用root权限则会修改一些系统文件会出问题
  // root-check的1.0.0版本是amd，2.0.0版本是cmd（import）
  const rootCheck = require("root-check");
  rootCheck();
}

// *** 4.检查系统主用户目录，并判断是否存在该文件 ***
function checkUserHome() {
  if (userhome()) {
    if (pathExists(userhome())) {
      return;
    }
  }
  throw Error(colors.red('请检查用户主目录'))
}

// // *** 5.检查入参（是否启动debug模式【被on:debug取代】 ***
// function checkInputArgs() {
//   argv = require('minimist')(process.argv.slice(2));
//   if (argv.debug) {
//     process.env.LOG_LEVEL = 'verbose';
//   }
//   log.level = process.env.LOG_LEVEL;
// }

// *** 6.检查环境变量 ***
function checkEnv() {
  const dotEnv = require('dotenv');
  // 此时检测出当前的目录下没有.env文件，我们需要为其指定env文件
  // 1-先去主目录下找env文件
  if (pathExists(path.resolve(userhome()), '.env')) {
    // config方法是将当前环境变量设置为指定的env文件
    dotEnv.config({
      path: path.resolve(userhome(), '.env')
    });
  }
  let config = dotEnv.config()
  // 2-如果当前执行目录下也没有env文件
  createDefaultConfig()
}

function createDefaultConfig() {
  const cliConfig = {
    home: userhome(),
  };
  if (process.env.CLI_HOME) {
    cliConfig['cliHome'] = path.join(userhome(), process.env.CLI_HOME);
  } else {
    cliConfig['cliHome'] = path.join(userhome(), constant.DEFAULT_CLI_HOME);
  }
  process.env.CLI_HOME_PATH = cliConfig.cliHome;
}

// *** 7.检查@gsh-cli是否为最新版本 ***
async function checkNpmVersion() {
  // 1.获取当前的版本号跟包名
  const pkgVersion = pkg.version
  const pkgName = pkg.name

  // 2.获取npm所有版本
  const { getNpmSemverVersions } = require('@gsh-cli/npm-get-info')

  // 3.提取版本，并获取比现版本新的版本合集
  const lastVersion = await getNpmSemverVersions(pkgVersion, pkgName)
  if(lastVersion && semver.gt(lastVersion, pkgVersion)) {
    log.warn("更新提示",colors.yellow(`请手动更新${pkgName}，当前版本是${pkgVersion}，最新版本是${lastVersion}，更新命令是npm install -g ${pkgName}`))
  }

}

